home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
scheme
/
boxer
/
boxer.lha
/
grobjs.lisp
< prev
next >
Wrap
Text File
|
1993-07-17
|
12KB
|
337 lines
;; -*- Mode:LISP; Package:BOXER; Base:10.;fonts:cptfont; -*-
;;
;; Copyright 1984 Massachusetts Institute of Technology
;;
;; Permission to use, copy, modify, distribute, and sell this software
;; and its documentation for any purpose is hereby granted without fee,
;; provided that the above copyright notice appear in all copies and that
;; both that copyright notice and this permission notice appear in
;; supporting documentation, and that the name of M.I.T. not be used in
;; advertising or publicity pertaining to distribution of the software
;; without specific, written prior permission. M.I.T. makes no
;; representations about the suitability of this software for any
;; purpose. It is provided "as is" without express or implied warranty.
;;
;;
;; +-Data--+
;; This file is part of the | BOXER | system
;; +-------+
;;
;; Graphics Object Definitions
;; Coordinate Transformation and Drawing Utilities
;; Also mouse-sensitivity code.
;;; Each slot in the turlte flavor holds a dotted pair consisting of
;;; the value of the slot in lisp and the box which holds the value in Boxer
;;; All the turtle mutators keep these two things in synch. The second half
;;; dotted pair is nil if the sprite is missing a box for that state variable.
(DEFFLAVOR TURTLE
((X-POSITION '(0.))
(Y-POSITION '(0.))
(ASSOC-GRAPHICS-BOX NIL)
(SPRITE-BOX NIL)
(SHOWN-P '(T))
(PEN '(DOWN))
(HOME '((0 0 )))
(SUBSPRITES NIL)
(SUPERIOR-TURTLE NIL)
(HEADING (NCONS 0.))
(SHAPE (NCONS *TURTLE-SHAPE*))
(SIZE '(1.)))
()
(:SETTABLE-INSTANCE-VARIABLES SPRITE-BOX SUPERIOR-TURTLE)
(:GETTABLE-INSTANCE-VARIABLES ASSOC-GRAPHICS-BOX SPRITE-BOX SUBSPRITES)
:INITABLE-INSTANCE-VARIABLES)
(DEFMETHOD (TURTLE :DUMP-FORM) ()
(LIST 'TURTLE :X-POSITION (NCONS (CAR X-POSITION)) :Y-POSITION (NCONS (CAR Y-POSITION))
:SHOWN-P (NCONS (CAR SHOWN-P)) :PEN (NCONS (CAR PEN)) :HOME (NCONS (CAR HOME))
:HEADING (NCONS (CAR HEADING)) :SHAPE (NCONS (CAR SHAPE)) :SIZE (NCONS (CAR SIZE))))
(DEFUN MAKE-TURTLE ()
(MAKE-INSTANCE 'TURTLE))
(DEFMETHOD (TURTLE :SET-SPRITE-BOX) (BOX)
(SETQ SPRITE-BOX BOX))
(DEFMETHOD (TURTLE :COPY) ()
(MAKE-INSTANCE 'TURTLE
':X-POSITION (NCONS (CAR X-POSITION))
':Y-POSITION (NCONS (CAR Y-POSITION))
':HEADING (NCONS (CAR HEADING))
':SHOWN-P (NCONS (CAR SHOWN-P))
':PEN (NCONS (CAR PEN))
':HOME (NCONS (CAR HOME))
':SHAPE (NCONS (CAR SHAPE))
':SIZE (NCONS (CAR SIZE))))
(DEFTYPE-CHECKING-MACROS TURTLE "A Turtle")
;;; Some useful variables that various types of objects need
(DEFCONST *DEFAULT-GRAPHICS-OBJECT-HEIGHT* 10.0)
(DEFCONST *DEFAULT-GRAPHICS-OBJECT-WIDTH* 10.0)
;;; turtle shape
(DEFCONST *TURTLE-HEIGHT* 15.0)
(DEFCONST *TURTLE-HALF-BASE* 5.0)
(DEFCONST *TURTLE-SHAPE*
(LIST :UP 0 (* .333 *TURTLE-HEIGHT*) :DOWN
(- *TURTLE-HALF-BASE*) 0
*TURTLE-HALF-BASE* (- *TURTLE-HEIGHT*)
*TURTLE-HALF-BASE* *TURTLE-HEIGHT*
(- *TURTLE-HALF-BASE*) 0
:UP 0 (- (* .333 *TURTLE-HEIGHT*))))
;;; Adding and removing graphics-objects to/from GRAPHICS-BOXES
(DEFMETHOD (GRAPHICS-BOX :ADD-GRAPHICS-OBJECT) (NEW-OBJECT)
(TELL NEW-OBJECT :SET-ASSOC-GRAPHICS-BOX SELF)
(SETF (GRAPHICS-SHEET-OBJECT-LIST GRAPHICS-SHEET)
(PUSH NEW-OBJECT (GRAPHICS-SHEET-OBJECT-LIST GRAPHICS-SHEET))))
(DEFMETHOD (GRAPHICS-BOX :REMOVE-GRAPHICS-OBJECT) (OLD-OBJECT)
(WHEN (EQ (TELL OLD-OBJECT :ASSOC-GRAPHICS-BOX) SELF)
(TELL OLD-OBJECT :SET-ASSOC-GRAPHICS-BOX NIL)
(SETF (GRAPHICS-SHEET-OBJECT-LIST GRAPHICS-SHEET)
(DELQ OLD-OBJECT (GRAPHICS-SHEET-OBJECT-LIST GRAPHICS-SHEET)))))
(DEFMETHOD (GRAPHICS-DATA-BOX :ADD-GRAPHICS-OBJECT) (NEW-OBJECT)
(TELL NEW-OBJECT :SET-ASSOC-GRAPHICS-BOX SELF)
(SETF (GRAPHICS-SHEET-OBJECT-LIST GRAPHICS-SHEET)
(PUSH NEW-OBJECT (GRAPHICS-SHEET-OBJECT-LIST GRAPHICS-SHEET))))
(DEFMETHOD (GRAPHICS-DATA-BOX :REMOVE-GRAPHICS-OBJECT) (OLD-OBJECT)
(WHEN (EQ (TELL OLD-OBJECT :ASSOC-GRAPHICS-BOX) SELF)
(TELL OLD-OBJECT :SET-ASSOC-GRAPHICS-BOX NIL)
(SETF (GRAPHICS-SHEET-OBJECT-LIST GRAPHICS-SHEET)
(DELQ OLD-OBJECT (GRAPHICS-SHEET-OBJECT-LIST GRAPHICS-SHEET)))))
;;; Mouse Sensitivity
(DEFMETHOD (SPRITE-BLINKER :OFF) ()
(TELL SELF :SET-VISIBILITY NIL)
(SETQ SELECTED-SPRITE NIL))
;;; reset the sprite blinker after every change
(DEFMETHOD (GRAPHICS-BOX :AFTER :MODIFIED) (IGNORE)
(TELL *SPRITE-BLINKER* :OFF))
;;; this does the highlighting
(DEFMETHOD (SCREEN-BOX :HIGHLIGHT-SPRITE-UNDER-MOUSE) (X Y)
(LET ((G-BOX (IF (GRAPHICS-BOX? ACTUAL-OBJ)
ACTUAL-OBJ
(TELL ACTUAL-OBJ :PORTS))))
(WITH-GRAPHICS-VARS-BOUND G-BOX
(WITH-TURTLE-SLATE-ORIGINS SELF
(LET ((USER-X (USER-COORDINATE-X (- X %ORIGIN-X-OFFSET)))
(USER-Y (USER-COORDINATE-Y (- Y %ORIGIN-Y-OFFSET 1))))
(LET ((SPRITE (FIND-SPRITE-UNDER-POINT
USER-X USER-Y
(GRAPHICS-SHEET-OBJECT-LIST GR-SHEET))))
(IF (NULL SPRITE)
(TELL *SPRITE-BLINKER* :OFF)
(TELL *SPRITE-BLINKER* :HIGHLIGHT-SPRITE SPRITE SELF))))))))
(DEFVAR *MOUSING-ALLOWABLE-ERROR* 5 "Allowed error when pointing to a sprite with the mouse")
(DEFUN FIND-SPRITE-UNDER-POINT (USER-X USER-Y OBJECT-LIST
&AUX SPRITE (SPRITE-AREA 999999)
LEFT TOP RIGHT BOTTOM OBJECT-AREA OBJECT)
(TAGBODY
LOOP
(SETQ OBJECT (CAR OBJECT-LIST))
(SETQ OBJECT-LIST (CDR OBJECT-LIST))
(WHEN (AND (TURTLE? OBJECT) (TELL OBJECT :ABSOLUTE-SHOWN-P))
(MULTIPLE-VALUE (LEFT TOP RIGHT BOTTOM)
(TELL OBJECT :ENCLOSING-RECTANGLE))
(SETQ OBJECT-AREA (ABS (* (- LEFT RIGHT) (- TOP BOTTOM))))
(WHEN (AND (< OBJECT-AREA SPRITE-AREA)
(INCLUSIVE-BETWEEN? USER-X
LEFT
(+ RIGHT *MOUSING-ALLOWABLE-ERROR*))
(INCLUSIVE-BETWEEN? USER-Y
(- BOTTOM *MOUSING-ALLOWABLE-ERROR*)
TOP)
(SETQ SPRITE-AREA OBJECT-AREA SPRITE OBJECT)))
(SETQ OBJECT-LIST (APPEND OBJECT-LIST (TELL OBJECT :SUBSPRITES))))
(WHEN OBJECT-LIST (GO LOOP)))
SPRITE)
;;; call this method only within WITH-TURTLE-SLATE-ORIGINS.
(DEFMETHOD (SPRITE-BLINKER :HIGHLIGHT-SPRITE) (SPRITE SCREEN-BOX)
(MULTIPLE-VALUE-BIND (LEFT TOP RIGHT BOTTOM)
(TELL SPRITE :ENCLOSING-RECTANGLE)
(LET ((ARRAY-LEFT (MAX (FIX-ARRAY-COORDINATE-X LEFT) -1.))
(ARRAY-TOP (MAX (FIX-ARRAY-COORDINATE-Y TOP) -1.))
(ARRAY-RIGHT (MIN (FIX-ARRAY-COORDINATE-X RIGHT) (1+ %DRAWING-WIDTH)))
(ARRAY-BOTTOM (MIN (FIX-ARRAY-COORDINATE-Y BOTTOM) (1+ %DRAWING-HEIGHT))))
(LET ((X (+ -2. %ORIGIN-X-OFFSET ARRAY-LEFT))
(Y (+ -2. %ORIGIN-Y-OFFSET ARRAY-TOP))
(WIDTH (- ARRAY-RIGHT ARRAY-LEFT -2.))
(HEIGHT (- ARRAY-BOTTOM ARRAY-TOP -2.)))
(TELL SELF :SET-CURSORPOS X Y )
(TELL SELF :SET-SIZE WIDTH HEIGHT)
(TELL SELF :SET-VISIBILITY T))))
(SETQ SELECTED-SPRITE SPRITE)
(SETQ SPRITE-SCREEN-BOX SCREEN-BOX))
;;; coordinate transformations.
;;;
;;; ARRAY coordinates are referenced to the indices of the bit-array of the graphics box
;;; therefore in ARRAY coordinates, (0, 0) is in the upper-left hand corner whereas...
;;; ...in USER coordinates, which refer to the coordinates in which the user talks to the
;;; object, (0, 0) will be more or less in the middle of the box.
;;;
;;; USER ARRAY
(DEFUN FIX-ARRAY-COORDINATE-X (USER-X)
(FIXR (ARRAY-COORDINATE-X USER-X)))
(DEFUN ARRAY-COORDINATE-X (USER-X)
(+ (// %DRAWING-WIDTH 2) USER-X))
(DEFUN FIX-ARRAY-COORDINATE-Y (USER-Y)
(FIXR (ARRAY-COORDINATE-Y USER-Y)))
(DEFUN ARRAY-COORDINATE-Y (USER-Y)
(- (// %DRAWING-HEIGHT 2) (* USER-Y *SCRUNCH-FACTOR*)))
;;; ARRAY USER
(DEFUN USER-COORDINATE-X (ARRAY-X)
(- ARRAY-X (// %DRAWING-WIDTH 2)))
(DEFUN USER-COORDINATE-Y (ARRAY-Y)
(// (- (// %DRAWING-HEIGHT 2) ARRAY-Y) *SCRUNCH-FACTOR*))
;;; these want ARRAY coordinates
(DEFUN POINT-IN-ARRAY? (X Y)
(AND (X-IN-ARRAY? X)
(Y-IN-ARRAY? Y)))
(DEFUN X-IN-ARRAY? (X)
(AND ( X 0) (< X %DRAWING-WIDTH)))
(DEFUN Y-IN-ARRAY? (Y)
(AND ( Y 0) (< Y %DRAWING-HEIGHT)))
;;; normalize coordinates to the on screen position
(DEFUN WRAP-OBJECT-COORDS (OBJECT)
(TELL OBJECT :SET-X-POSITION (WRAP-X-COORDINATE (TELL OBJECT :X-POSITION)))
(TELL OBJECT :SET-Y-POSITION (WRAP-Y-COORDINATE (TELL OBJECT :Y-POSITION))))
(DEFUN WRAP-X-COORDINATE (USER-X)
(USER-COORDINATE-X (FLOAT-MODULO (ARRAY-COORDINATE-X USER-X) %DRAWING-WIDTH)))
(DEFUN WRAP-Y-COORDINATE (USER-Y)
(USER-COORDINATE-Y (FLOAT-MODULO (ARRAY-COORDINATE-Y USER-Y) %DRAWING-HEIGHT)))
(DEFUN FLOAT-MODULO (NUM MOD)
(LET ((X (- NUM (* (FIX (// NUM MOD)) MOD))))
(IF (MINUSP X) (+ X MOD) X)))
;;; ******************************************************************
;;; Everything after this line has been made obsolete by sprite boxes.
;;; and is only here for reference.
;;; ******************************************************************
;;; Here is the basic flavor
;;; This defines a graphics object by its location only. Anything built out of this should
;;; define its own methods for saving (in files) and displaying
;(DEFFLAVOR MINIMUM-GRAPHICS-OBJECT
; ((X-POSITION 0.)
; (Y-POSITION 0.)
; (assoc-graphics-box NIL))
; ()
; :GETTABLE-INSTANCE-VARIABLES
; :SETTABLE-INSTANCE-VARIABLES
; :INITABLE-INSTANCE-VARIABLES
; (:REQUIRED-METHODS :DRAW :ERASE)
; (:DOCUMENTATION :ESSENTIAL-MIXIN
; "All other graphics objects are built on top of this flavor. "))
(DEFTYPE-CHECKING-MACROS GRAPHICS-OBJECT "A graphics object")
;;; some useful MIXINS
;(DEFFLAVOR EXPORTING-NAME-MIXIN
; ((NAME NIL))
; ()
; :GETTABLE-INSTANCE-VARIABLES
; :INITABLE-INSTANCE-VARIABLES
; (:REQUIRED-FLAVORS MINIMUM-GRAPHICS-OBJECT)
; (:DOCUMENTATION :MIXIN
; "Gives the object a name so it can be accessed from outside of the Graphics Box. "))
;;; BASIC methods that EVERY ONE uses
;;; higher level object generally should define their own main method for the following
;;; made obsolete by sprite boxes
;(DEFMETHOD (MINIMUM-GRAPHICS-OBJECT :GRAPHICS-BOX) ()
; (GRAPHICS-SHEET-SUPERIOR-BOX ASSOCIATED-SHEET))
;
;(DEFMETHOD (MINIMUM-GRAPHICS-OBJECT :BEFORE :SET-ASSOCIATED-SHEET) (NEW-SHEET)
; (WHEN (AND (NEQ NEW-SHEET ASSOCIATED-SHEET) (NOT-NULL ASSOCIATED-SHEET))
; (TELL SELF :ERASE)))
;
;(DEFMETHOD (MINIMUM-GRAPHICS-OBJECT :AFTER :SET-ASSOCIATED-SHEET) (NEW-SHEET)
; (WHEN (NOT-NULL NEW-SHEET)
; (TELL SELF :DRAW)))
;
;(DEFMETHOD (MINIMUM-GRAPHICS-OBJECT :DESCRIPTION-LIST) ()
; "This method should return a list of lists suitable for MAKE-BOX"
; (LIST (NCONS (FORMAT NIL "I am a ~A" (TYPEP SELF)))
; (NCONS (FORMAT NIL "X-position ~D" X-POSITION))
; (NCONS (FORMAT NIL "Y-Position ~D" Y-POSITION))))
;
;(DEFMETHOD (MINIMUM-GRAPHICS-OBJECT :DRAW) ()
; "This draw method assumes that position (0, 0) is in the upper left hand corner.
;Higher level draw methods which want (0, 0) to be elsewhere (like the
; middle) should
;convert x and y positions before calling DRAW-LINE. "
; (WITH-GRAPHICS-VARS-BOUND (GRAPHICS-SHEET-SUPERIOR-BOX ASSOCIATED-SHEET)
; (CK-MODE-DRAW-LINE X-POSITION Y-POSITION (+ X-POSITION *DEFAULT-GRAPHICS-OBJECT-WIDTH*)
; (+ Y-POSITION *DEFAULT-GRAPHICS-OBJECT-HEIGHT*))
; (CK-Mode-DRAW-LINE (+ X-POSITION *DEFAULT-GRAPHICS-OBJECT-WIDTH*) Y-POSITION
; X-POSITION (+ Y-POSITION *DEFAULT-GRAPHICS-OBJECT-HEIGHT*))))
;
;(DEFMETHOD (MINIMUM-GRAPHICS-OBJECT :ERASE) ()
; (TELL SELF :DRAW))
;
;;; Methods for MIXINs
;;; a crock so that TELL will work
;(DEFMETHOD (EXPORTING-NAME-MIXIN :LOOKUP-STATIC-VARIABLE-CHECK-SUPERIORS) (VAR)
; (TELL-CHECK-NIL (GRAPHICS-SHEET-SUPERIOR-BOX ASSOCIATED-SHEET)
; :LOOKUP-STATIC-VARIABLE-CHECK-SUPERIORS VAR))
;
;(DEFMETHOD (EXPORTING-NAME-MIXIN :BEFORE :SET-ASSOCIATED-SHEET) (NEW-SHEET)
; (COND ((AND (NULL NEW-SHEET) (NOT-NULL ASSOCIATED-SHEET))
; (TELL (GRAPHICS-SHEET-SUPERIOR-BOX ASSOCIATED-SHEET)
; :REMOVE-ALL-STATIC-BINDINGS SELF))
; ((AND (NEQ NEW-SHEET ASSOCIATED-SHEET)(NOT-NULL NEW-SHEET)(NOT-NULL ASSOCIATED-SHEET))
; (LET ((SURROUNDING-BOX (GRAPHICS-SHEET-SUPERIOR-BOX NEW-SHEET)))
; (TELL (GRAPHICS-SHEET-SUPERIOR-BOX ASSOCIATED-SHEET)
; :REMOVE-ALL-STATIC-BINDINGS SELF)
; (WHEN (AND NAME (SYMBOLP NAME))
; (TELL SURROUNDING-BOX :ADD-STATIC-VARIABLE-PAIR NAME SELF)
; (TELL SURROUNDING-BOX :EXPORT-VARIABLE NAME))))))
;